/*
 * TepcoMeter:TepcoMetterWidgetService.java
 * Copyright © 2011 ho9ho9 All Rights Reserved.
 */
package com.ho9ho9.tepcometer;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader.TileMode;
import android.os.IBinder;
import android.util.Log;
import android.widget.RemoteViews;

import com.ho9ho9.tepcometer.dto.WattDto;
import com.ho9ho9.tepcometer.util.HttpUtils;

/**
 * TepcoMetterWidgetServiceクラス.
 * @author ho9ho9
 */
public class TepcoMetterWidgetService extends Service {

	private static final String TAG_NAME = "TepcoMetterWidgetService";
	private static final String JSON_DATA_URL = "http://denki.cuppat.net/data/%s.json";
	private static final DateFormat PARSE_UPDATED = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private static final DateFormat FORMAT_UPDATED = new SimpleDateFormat("MM/dd HH:mm");
	private static final DateFormat FORMAT_URL_DATE = new SimpleDateFormat("yyyyMMdd");
	
	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.d(TAG_NAME, "startId:" + startId);
		// 既存処理呼び出し
		super.onStart(intent, startId);
		
		// Widget情報取得
		AppWidgetManager manager = AppWidgetManager.getInstance(this);
		RemoteViews views = new RemoteViews(getPackageName(), R.layout.tepcometer);
		
		// 当日の消費電力を取得
		WattDto wattDto = getWattInfo();
		if (wattDto != null) {
			// 取得結果を反映
			reflectViews(views, wattDto);
			// Widgetを更新
			manager.updateAppWidget(new ComponentName(this, TepcoMetterWidgetProvider.class), views);
		} else {
			// 当日の消費電力を取得できなかった場合
			Log.e(TAG_NAME, "use watt data failed!");
		}
		
		Log.d(TAG_NAME, "service end");
	}

	private void reflectViews(RemoteViews views, WattDto wattDto) {
		// 結果から値を設定
		Integer currentWatt = wattDto.getHours().get(wattDto.getHours().size() - 1);
		Integer calcRet = calculateUseWatt(currentWatt, wattDto.getCapability());
		views.setTextViewText(R.id.useWatt, calcRet.toString());
		views.setTextViewText(R.id.updateDate, FORMAT_UPDATED.format(wattDto.getUpdated()));
		views.setTextViewText(R.id.currentWatt, currentWatt.toString());
		views.setTextViewText(R.id.maxWatt, wattDto.getCapability().toString());

		// グラフ描画
		drowGraph(views, calcRet);
	}

	private void drowGraph(RemoteViews views, Integer calcRet) {
		// グラフ描画
		Bitmap mainParts = BitmapFactory.decodeResource(getResources(), R.drawable.left_parts_main);
		Bitmap bitmap = Bitmap.createBitmap(mainParts.getWidth(), mainParts.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(bitmap);
		Paint paint = new Paint();
		LinearGradient gr = new LinearGradient(
				0, calculateGraphOffset(mainParts.getHeight(), calcRet), 0, mainParts.getHeight(),
				getWattMetterGradientColor(calcRet), null, TileMode.CLAMP);
		paint.setShader(gr);
		canvas.drawRect(0, calculateGraphOffset(mainParts.getHeight(), calcRet), mainParts.getWidth(), mainParts.getHeight(), paint);
		views.setImageViewBitmap(R.id.graphCanvasView, bitmap);
	}

	private WattDto getWattInfo() {
		Calendar cal = Calendar.getInstance();
		// 当日電力情報取得
		String jsonStr = HttpUtils.get(generateCurrentJsonDataUrl(cal));
		if ((jsonStr == null) || (jsonStr.length() == 0)) {
			// 前日電力情報取得
			cal.add(Calendar.DATE, -1);
			jsonStr = HttpUtils.get(generateCurrentJsonDataUrl(cal));
		}
		// 結果解析
		return parseJsonData(jsonStr);
	}

	private float calculateGraphOffset(int height, Integer calcRet) {
		// 開始位置のため100（MAX）から現在の利用率を引いたものに1%分の積を求める
		return (new Float(height) / 100) * (100 - calcRet);
	}

	private int[] getWattMetterGradientColor(Integer calcRet) {
		int[] result = null;
		if (calcRet < 90) {
			result = new int[] {0xff2df86e, 0xff8ffbb2};
		} else if (calcRet < 96) {
			result = new int[] {0xffffe32a, 0xfffff3a1};
		} else {
			result = new int[] {0xffff2257, 0xffff99b1};
		}
		return result;
	}

	private String generateCurrentJsonDataUrl(Calendar cal) {
		return String.format(JSON_DATA_URL, FORMAT_URL_DATE.format(cal.getTime()));
	}

	private Integer calculateUseWatt(Integer currentWatt, Integer capability) {
		Float calcRet = (new Float(currentWatt) / new Float(capability)) * 100;
		return Math.round(calcRet);
	}

	private WattDto parseJsonData(String jsonStr) {
		WattDto result = null;
		try {
			if ((jsonStr != null) && (jsonStr.length() > 0)) {
				result = new WattDto();
				JSONObject jsonObj = new JSONObject(jsonStr);
				result.setHours(getHours(jsonObj.getJSONArray("hours")));
				result.setCapability(parseInt(jsonObj.getString("capability")));
				result.setUpdated(parseUpdatedDate(jsonObj.getString("updated")));
			}
		} catch (JSONException e) {
			Log.e(TAG_NAME, e.getMessage(), e);
		}
		return result;
	}

	private List<Integer> getHours(JSONArray hours) throws JSONException {
		List<Integer> result = new ArrayList<Integer>();
		if (hours != null) {
			for (int i = 0; i < hours.length(); i++) {
				result.add(parseInt(hours.getString(i)));
			}
		}
		return result;
	}

	private Integer parseInt(String str) {
		Integer result = null;
		try {
			if (str != null) {
				result = Integer.parseInt(str, 10);
			}
		} catch (Exception e) {
			Log.e(TAG_NAME, e.getMessage(), e);
		}
		return result;
	}

	private Date parseUpdatedDate(String str) {
		Date result = null;
		try {
			if (str != null) {
				result = PARSE_UPDATED.parse(str);
			}
		} catch (ParseException e) {
			Log.e(TAG_NAME, e.getMessage(), e);
		}
		return result;
	}

}
